#pragma once

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include "Server.h"
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>

#using <mscorlib.dll>
#using <system.windows.forms.dll>
#using <system.dll>
#using <system.drawing.dll>

#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"advapi32.lib")

#define INFO_BUFFER_SIZE 32767

System::String ^ returnUserName() {
	TCHAR infoBuf[INFO_BUFFER_SIZE];
	DWORD bufCharCount = INFO_BUFFER_SIZE;
	GetUserName(infoBuf, &bufCharCount);
	return tchar2StringRef(infoBuf);
}

System::String ^ returnCompName() {
	TCHAR infoBuf[INFO_BUFFER_SIZE];
	DWORD bufCharCount = INFO_BUFFER_SIZE;
	GetComputerName(infoBuf, &bufCharCount);
	return tchar2StringRef(infoBuf);
}

namespace DirectoryCompareTool {

	using namespace std;
	using namespace System;
	using namespace System::IO;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace System::Runtime::InteropServices;

	bool singleUserBool = true;
	bool errorsFound = false;
	int fileCount = 0;
	OSVERSIONINFO osvi;
	BOOL bIsWindowsVistaorLater;

	/// <summary>
	/// Summary for Form1
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			/*determine OS*/
			ZeroMemory(&osvi,sizeof(OSVERSIONINFO));
			osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
			GetVersionEx(&osvi);
			bIsWindowsVistaorLater = (osvi.dwMajorVersion >= 6);

			InitializeComponent();

			/*determine username, computer name, display OS info*/
			this->username->Text = returnUserName();
			this->computer->Text = returnCompName();
			if (bIsWindowsVistaorLater) this->toolStripStatusLabel3->Text = String::Format("OS: {0}",L"Vista/7");
			else this->toolStripStatusLabel3->Text = String::Format("OS: {0}",L"XP");
		}

		void mapDirectory(String^ drive,String^ location) {
			String^ directoryCmd = "net use " + drive + ": " + location;
			const char* str = (char*)(void*)Marshal::StringToHGlobalAnsi(directoryCmd);
			system(str);
		}

		void unmapDirectory(String^ drive) {
			String^ directoryCmd = "net use " + drive + ": /d /y";
			const char* str = (char*)(void*)Marshal::StringToHGlobalAnsi(directoryCmd);
			system(str);
		}

		bool FileCompare(String ^file1, String ^file2) {
			int file1byte;
			int file2byte;
			FileStream ^fs1;
			FileStream ^fs2;

			file1 = file1->Trim();
			file2 = file2->Trim();

			// Determine if the same file was referenced two times.
			if (String::Equals(file1,file2)) {
				// Return true to indicate that the files are the same.
				return true;
			}

			// Open the two files.
			try {
				fs1 = gcnew FileStream(file1, FileMode::Open);
				fs2 = gcnew FileStream(file2, FileMode::Open);

				// Check the file sizes. If the sizes are different, the files 
				// are different.
				if (fs1->Length != fs2->Length) {
					// Close the file
					fs1->Close();
					fs2->Close();
					// Return false to indicate files are different
					return false;
				}

				// Read and compare a byte from each file until either a
				// non-matching set of bytes is found or until the end of
				// file1 is reached.
				do  {
					// Read one byte from each file.
					file1byte = fs1->ReadByte();
					file2byte = fs2->ReadByte();
				}
				while ((file1byte == file2byte) && (file1byte != -1));

				// Close the files.
				fs1->Close();
				fs2->Close();
			}


			catch(Exception ^ex) {
				if(fs1) {
					fs1->Close();
				}
				if(fs2) {
					fs2->Close();
				}
				if (Marshal::GetHRForException(ex) == -2147024894) {
					errorsFound = true;
					Console::Write("\nError - File Not Found: " + file1 + "\n");
				}
			}

			// Return the success of the comparison. "file1byte" is 
			// equal to "file2byte" at this point only if the files are 
			// the same.
			return ((file1byte - file2byte) == 0);
		}

		void setFileCount() {
			char line[1024];
			FILE *pFile;
			pFile = fopen("Q:\\dirOut.txt","r");
			if (pFile != NULL) {
				while (!feof(pFile)) {
					fileCount++;
					fgets(line,1024,pFile);
				}
			}
			fclose(pFile);
		}

		void evaluate() {
			Console::Write("");
			float percent = 0;
			float total = fileCount;
			char line[1024]; char line2[1024]; 
			int iteration = 1;
			FILE * pFile;
			pFile = fopen("Q:\\dirOut.txt","r");
			if (pFile != NULL) {
				while (!feof(pFile)) {
					percent = ceil((iteration / total)*100);
					//if (percent < 10) Console::Write("0" + percent + "% (" + iteration + "/" + total + ")\n");
					//else Console::Write(percent + "% (" + iteration + "/" + total + ")\n");
					fgets(line,1024,pFile);
					strcpy(line2,line);
					line2[0] = getDriveLetter();
					String^ file1 = gcnew String(line);
					String^ file2 = gcnew String(line2);
					for (int i=0;i < file1->Length;i++) {
						if (file1->Substring(i,1) == "\\") {
							file1 = file1->Insert(i,L"\\"); file2 = file2->Insert(i,L"\\");
							i++;
						}
					}
					if (!FileCompare(file1,file2)) {
						errorsFound = true;
						Console::Write("Error - Corrupt: " + file1 + "\n");
					}
					iteration++;
				}
			}
			fclose(pFile);
		}

		void createFolderList(String^ drive) {
			String^ directoryCmd = "";
			if (singleUserBool && bIsWindowsVistaorLater) directoryCmd = "dir " + drive + ":\\Users\\" + this->username->Text + " /a-D/b/s > " + drive + ":\\dirOut.txt";
			else if (!singleUserBool && bIsWindowsVistaorLater) directoryCmd = "dir " + drive + ":\\Users\\ /a-D/b/s > " + drive + ":\\dirOut.txt";
			else if (singleUserBool && !bIsWindowsVistaorLater) directoryCmd = "dir \"" + drive + ":\\Documents and Settings\\" + this->username->Text + "\" /a-D/b/s > " + drive + ":\\dirOut.txt";
			else if (!singleUserBool && !bIsWindowsVistaorLater) directoryCmd = "dir \"" + drive + ":\\Documents and Settings\\\" /a-D/b/s > " + drive + ":\\dirOut.txt";
			const char* str = (char*)(void*)Marshal::StringToHGlobalAnsi(directoryCmd);
			system(str);
		}

		System::String ^ getBackupServer() {
			System::String ^ sysBackupServer = (gcnew System::String(backupServer));
			return sysBackupServer;
		}

		char getDriveLetter() {
			return driveLetter[0];
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::Label^  label1;
	private: System::Windows::Forms::TextBox^  username;
	private: System::Windows::Forms::Label^  label2;
	private: System::Windows::Forms::DateTimePicker^  dateTimePicker1;
	private: System::Windows::Forms::Label^  label3;
	private: System::Windows::Forms::TextBox^  computer;
	private: System::Windows::Forms::MenuStrip^  menuStrip1;
	private: System::Windows::Forms::ToolStripMenuItem^  fileToolStripMenuItem;
	private: System::Windows::Forms::ToolStripMenuItem^  exitToolStripMenuItem;
	private: System::Windows::Forms::ToolStripMenuItem^  settingsToolStripMenuItem;
	private: System::Windows::Forms::ToolStripMenuItem^  serverSettingsToolStripMenuItem;
	private: System::Windows::Forms::Button^  launch;
	private: System::Windows::Forms::StatusStrip^  statusStrip1;
	private: System::Windows::Forms::ToolStripStatusLabel^  toolStripStatusLabel1;
	private: System::Windows::Forms::RadioButton^  singleUserRadio;
	private: System::Windows::Forms::RadioButton^  allUserRadio;
	private: System::Windows::Forms::ToolStripStatusLabel^  toolStripStatusLabel2;
	private: System::Windows::Forms::ToolStripStatusLabel^  toolStripStatusLabel3;


	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>
		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			System::ComponentModel::ComponentResourceManager^  resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid));
			this->label1 = (gcnew System::Windows::Forms::Label());
			this->username = (gcnew System::Windows::Forms::TextBox());
			this->label2 = (gcnew System::Windows::Forms::Label());
			this->dateTimePicker1 = (gcnew System::Windows::Forms::DateTimePicker());
			this->label3 = (gcnew System::Windows::Forms::Label());
			this->computer = (gcnew System::Windows::Forms::TextBox());
			this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip());
			this->fileToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->exitToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->settingsToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->serverSettingsToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->launch = (gcnew System::Windows::Forms::Button());
			this->statusStrip1 = (gcnew System::Windows::Forms::StatusStrip());
			this->toolStripStatusLabel1 = (gcnew System::Windows::Forms::ToolStripStatusLabel());
			this->toolStripStatusLabel3 = (gcnew System::Windows::Forms::ToolStripStatusLabel());
			this->singleUserRadio = (gcnew System::Windows::Forms::RadioButton());
			this->allUserRadio = (gcnew System::Windows::Forms::RadioButton());
			this->menuStrip1->SuspendLayout();
			this->statusStrip1->SuspendLayout();
			this->SuspendLayout();
			// 
			// label1
			// 
			this->label1->AutoSize = true;
			this->label1->Location = System::Drawing::Point(13, 39);
			this->label1->Name = L"label1";
			this->label1->Size = System::Drawing::Size(58, 13);
			this->label1->TabIndex = 0;
			this->label1->Text = L"Username:";
			// 
			// username
			// 
			this->username->Location = System::Drawing::Point(77, 36);
			this->username->MaxLength = 8;
			this->username->Name = L"username";
			this->username->Size = System::Drawing::Size(200, 20);
			this->username->TabIndex = 1;
			// 
			// label2
			// 
			this->label2->AutoSize = true;
			this->label2->Location = System::Drawing::Point(13, 66);
			this->label2->Name = L"label2";
			this->label2->Size = System::Drawing::Size(33, 13);
			this->label2->TabIndex = 2;
			this->label2->Text = L"Date:";
			// 
			// dateTimePicker1
			// 
			this->dateTimePicker1->CustomFormat = L"dd-MMM-yy";
			this->dateTimePicker1->Format = System::Windows::Forms::DateTimePickerFormat::Custom;
			this->dateTimePicker1->Location = System::Drawing::Point(77, 64);
			this->dateTimePicker1->Name = L"dateTimePicker1";
			this->dateTimePicker1->Size = System::Drawing::Size(200, 20);
			this->dateTimePicker1->TabIndex = 3;
			// 
			// label3
			// 
			this->label3->AutoSize = true;
			this->label3->Location = System::Drawing::Point(13, 94);
			this->label3->Name = L"label3";
			this->label3->Size = System::Drawing::Size(55, 13);
			this->label3->TabIndex = 4;
			this->label3->Text = L"Computer:";
			// 
			// computer
			// 
			this->computer->Location = System::Drawing::Point(77, 91);
			this->computer->Name = L"computer";
			this->computer->Size = System::Drawing::Size(200, 20);
			this->computer->TabIndex = 5;
			// 
			// menuStrip1
			// 
			this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^  >(2) {this->fileToolStripMenuItem, 
				this->settingsToolStripMenuItem});
			this->menuStrip1->Location = System::Drawing::Point(0, 0);
			this->menuStrip1->Name = L"menuStrip1";
			this->menuStrip1->Size = System::Drawing::Size(438, 24);
			this->menuStrip1->TabIndex = 6;
			this->menuStrip1->Text = L"menuStrip1";
			// 
			// fileToolStripMenuItem
			// 
			this->fileToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^  >(1) {this->exitToolStripMenuItem});
			this->fileToolStripMenuItem->Name = L"fileToolStripMenuItem";
			this->fileToolStripMenuItem->Size = System::Drawing::Size(37, 20);
			this->fileToolStripMenuItem->Text = L"File";
			// 
			// exitToolStripMenuItem
			// 
			this->exitToolStripMenuItem->Name = L"exitToolStripMenuItem";
			this->exitToolStripMenuItem->Size = System::Drawing::Size(92, 22);
			this->exitToolStripMenuItem->Text = L"Exit";
			this->exitToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::exitToolStripMenuItem_Click);
			// 
			// settingsToolStripMenuItem
			// 
			this->settingsToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^  >(1) {this->serverSettingsToolStripMenuItem});
			this->settingsToolStripMenuItem->Name = L"settingsToolStripMenuItem";
			this->settingsToolStripMenuItem->Size = System::Drawing::Size(61, 20);
			this->settingsToolStripMenuItem->Text = L"Settings";
			// 
			// serverSettingsToolStripMenuItem
			// 
			this->serverSettingsToolStripMenuItem->Name = L"serverSettingsToolStripMenuItem";
			this->serverSettingsToolStripMenuItem->Size = System::Drawing::Size(160, 22);
			this->serverSettingsToolStripMenuItem->Text = L"Configuration...";
			this->serverSettingsToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::serverSettingsToolStripMenuItem_Click);
			// 
			// launch
			// 
			this->launch->Location = System::Drawing::Point(327, 61);
			this->launch->Name = L"launch";
			this->launch->Size = System::Drawing::Size(75, 23);
			this->launch->TabIndex = 7;
			this->launch->Text = L"Verify";
			this->launch->UseVisualStyleBackColor = true;
			this->launch->Click += gcnew System::EventHandler(this, &Form1::launch_Click);
			// 
			// statusStrip1
			// 
			this->statusStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^  >(2) {this->toolStripStatusLabel1, 
				this->toolStripStatusLabel3});
			this->statusStrip1->Location = System::Drawing::Point(0, 118);
			this->statusStrip1->Name = L"statusStrip1";
			this->statusStrip1->Size = System::Drawing::Size(438, 22);
			this->statusStrip1->SizingGrip = false;
			this->statusStrip1->TabIndex = 8;
			this->statusStrip1->Text = L"Backup Server:";
			// 
			// toolStripStatusLabel1
			// 
			this->toolStripStatusLabel1->Name = L"toolStripStatusLabel1";
			this->toolStripStatusLabel1->Size = System::Drawing::Size(189, 17);
			this->toolStripStatusLabel1->Text = L"Backup Server: \\\\trek\\userbackup$";
			// 
			// toolStripStatusLabel3
			// 
			this->toolStripStatusLabel3->ImageAlign = System::Drawing::ContentAlignment::MiddleRight;
			this->toolStripStatusLabel3->Name = L"toolStripStatusLabel3";
			this->toolStripStatusLabel3->Size = System::Drawing::Size(234, 17);
			this->toolStripStatusLabel3->Spring = true;
			this->toolStripStatusLabel3->Text = L"OS: ";
			// 
			// singleUserRadio
			// 
			this->singleUserRadio->AutoSize = true;
			this->singleUserRadio->Checked = true;
			this->singleUserRadio->Location = System::Drawing::Point(284, 39);
			this->singleUserRadio->Name = L"singleUserRadio";
			this->singleUserRadio->Size = System::Drawing::Size(79, 17);
			this->singleUserRadio->TabIndex = 9;
			this->singleUserRadio->TabStop = true;
			this->singleUserRadio->Text = L"Single User";
			this->singleUserRadio->UseVisualStyleBackColor = true;
			this->singleUserRadio->CheckedChanged += gcnew System::EventHandler(this, &Form1::singleUserRadio_CheckedChanged);
			// 
			// allUserRadio
			// 
			this->allUserRadio->AutoSize = true;
			this->allUserRadio->Location = System::Drawing::Point(370, 39);
			this->allUserRadio->Name = L"allUserRadio";
			this->allUserRadio->Size = System::Drawing::Size(66, 17);
			this->allUserRadio->TabIndex = 10;
			this->allUserRadio->Text = L"All Users";
			this->allUserRadio->UseVisualStyleBackColor = true;
			this->allUserRadio->CheckedChanged += gcnew System::EventHandler(this, &Form1::allUserRadio_CheckedChanged);
			// 
			// Form1
			// 
			this->AcceptButton = this->launch;
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(438, 140);
			this->Controls->Add(this->allUserRadio);
			this->Controls->Add(this->singleUserRadio);
			this->Controls->Add(this->statusStrip1);
			this->Controls->Add(this->launch);
			this->Controls->Add(this->computer);
			this->Controls->Add(this->label3);
			this->Controls->Add(this->dateTimePicker1);
			this->Controls->Add(this->label2);
			this->Controls->Add(this->username);
			this->Controls->Add(this->label1);
			this->Controls->Add(this->menuStrip1);
			this->MainMenuStrip = this->menuStrip1;
			this->MaximumSize = System::Drawing::Size(454, 178);
			this->MinimumSize = System::Drawing::Size(454, 178);
			this->Name = L"Form1";
			this->Text = L"UCCS Backup Verification";
			this->menuStrip1->ResumeLayout(false);
			this->menuStrip1->PerformLayout();
			this->statusStrip1->ResumeLayout(false);
			this->statusStrip1->PerformLayout();
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion
	private: System::Void exitToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {
				 Application::Exit();
			 }
	private: System::Void serverSettingsToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {
				 Server^ serverDialog = gcnew Server();
				 try {
					 serverDialog->ShowDialog(this);
				 }
				 finally {
					 delete serverDialog;
				 }
				 this->toolStripStatusLabel1->Text = String::Format("Backup Server: {0}", getBackupServer());
			 }
	 private: System::Void launch_Click(System::Object^  sender, System::EventArgs^  e) {
				 String^ driveLetter = L"Q";
				 mapDirectory(driveLetter,getBackupServer() + L"\\" + dateTimePicker1->Value.ToString("dd-MMM-yy") + L"_" + username->Text + L"_" + computer->Text);
				 createFolderList(driveLetter);
				 AllocConsole();
				 Console::Write("Evaluating, please wait (errors will be reported)...\n");
				 setFileCount();
				 evaluate();
				 if (errorsFound) Console::Write("\nErrors Found!\n");
				 else Console::Write("\nBackup verified. Proceed with build process.\n");
				 unmapDirectory(driveLetter);
			 }
	 private: System::Void singleUserRadio_CheckedChanged(System::Object^  sender, System::EventArgs^  e) {
				 singleUserBool = true;
			 }
	 private: System::Void allUserRadio_CheckedChanged(System::Object^  sender, System::EventArgs^  e) {
				 singleUserBool = false;
			 }
};
}